﻿using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WordNet.Core.ElementContracts;
using WordNet.Core.Extensions;

namespace WordNet.Core
{
    public class LexFile:ILexFile
    {

        public static readonly LexFile ADJ_ALL = new LexFile(0, "adj.all", "all adjective clusters", POS.GetPartOfSpeech(DbPartOfSpeechType.Adj));
        public static readonly LexFile ADJ_PERT = new LexFile(1, "adj.pert", "relational adjectives (pertainyms)", POS.GetPartOfSpeech(DbPartOfSpeechType.Adj));
        public static readonly LexFile ADV_ALL = new LexFile(2, "adv.all", "all adverbs", POS.GetPartOfSpeech(DbPartOfSpeechType.Adv));
        public static readonly LexFile NOUN_TOPS = new LexFile(3, "noun.Tops", "unique beginner for nouns", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_ACT = new LexFile(4, "noun.act", "nouns denoting acts or actions", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_ANIMAL = new LexFile(5, "noun.animal", "nouns denoting animals", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_ARTIFACT = new LexFile(6, "noun.artifact", "nouns denoting man-made objects", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_ATTRIBUTE = new LexFile(7, "noun.attribute", "nouns denoting attributes of people and objects", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_BODY = new LexFile(8, "noun.body", "nouns denoting body parts", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_COGNITION = new LexFile(9, "noun.cognition", "nouns denoting cognitive processes and contents", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_COMMUNICATION = new LexFile(10, "noun.communication", "nouns denoting communicative processes and contents", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_EVENT = new LexFile(11, "noun.event", "nouns denoting natural events", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_FEELING = new LexFile(12, "noun.feeling", "nouns denoting feelings and emotions", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_FOOD = new LexFile(13, "noun.food", "nouns denoting foods and drinks", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_GROUP = new LexFile(14, "noun.group", "nouns denoting groupings of people or objects", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_LOCATION = new LexFile(15, "noun.location", "nouns denoting spatial position", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_MOTIVE = new LexFile(16, "noun.motive", "nouns denoting goals", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_OBJECT = new LexFile(17, "noun.object", "nouns denoting natural objects (not man-made)", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_PERSON = new LexFile(18, "noun.person", "nouns denoting people", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_PHENOMENON = new LexFile(19, "noun.phenomenon", "nouns denoting natural phenomena", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_PLANT = new LexFile(20, "noun.plant", "nouns denoting plants", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_POSSESSION = new LexFile(21, "noun.possession", "nouns denoting possession and transfer of possession", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_PROCESS = new LexFile(22, "noun.process", "nouns denoting natural processes", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_QUANTITY = new LexFile(23, "noun.quantity", "nouns denoting quantities and units of measure", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_RELATION = new LexFile(24, "noun.relation", "nouns denoting relations between people or things or ideas", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_SHAPE = new LexFile(25, "noun.shape", "nouns denoting two and three dimensional shapes", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_STATE = new LexFile(26, "noun.state", "nouns denoting natural processes", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_SUBSTANCE = new LexFile(27, "noun.substance", "nouns denoting substances", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile NOUN_TIME = new LexFile(28, "noun.time", "nouns denoting time and temporal relations", POS.GetPartOfSpeech(DbPartOfSpeechType.Noun));
        public static readonly LexFile VERB_BODY = new LexFile(29, "verb.body", "verbs of grooming, dressing and bodily care", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_CHANGE = new LexFile(30, "verb.change", "verbs of size, temperature change, intensifying, etc.", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_COGNITION = new LexFile(31, "verb.cognition", "verbs of thinking, judging, analyzing, doubting", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_COMMUNICATION = new LexFile(32, "verb.communication", "verbs of telling, asking, ordering, singing", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_COMPETITION = new LexFile(33, "verb.competition", "verbs of fighting, athletic activities", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_CONSUMPTION = new LexFile(34, "verb.consumption", "verbs of eating and drinking", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_CONTACT = new LexFile(35, "verb.contact", "verbs of touching, hitting, tying, digging", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_CREATION = new LexFile(36, "verb.creation", "verbs of sewing, baking, painting, performing", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_EMOTION = new LexFile(37, "verb.emotion", "verbs of feeling", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_MOTION = new LexFile(38, "verb.motion", "verbs of walking, flying, swimming", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_PERCEPTION = new LexFile(39, "verb.perception", "verbs of seeing, hearing, feeling", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_POSESSION = new LexFile(40, "verb.possession", "verbs of buying, selling, owning", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_SOCIAL = new LexFile(41, "verb.social", "verbs of political and social activities and events", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_STATIVE = new LexFile(42, "verb.stative", "verbs of being, having, spatial relations", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile VERB_WEATHER = new LexFile(43, "verb.weather", "verbs of raining, snowing, thawing, thundering", POS.GetPartOfSpeech(DbPartOfSpeechType.Verb));
        public static readonly LexFile ADJ_PPL = new LexFile(44, "adj.ppl", "participial adjectives", POS.GetPartOfSpeech(DbPartOfSpeechType.Adj));
        static LexFile()
        {
            SetLexFileMap();
        }
       
        private readonly POS _pos; 
        private readonly int _num;
        private readonly String _name, _desc;

        protected LexFile(int num, String name, String desc, POS pos)
        {
            num.CheckLexicalFileNumber();
            name = CheckString(name);
            desc = CheckString(desc);

            _pos = pos;
            _num = num;
            _name = name;
            _desc = desc;
        }

        public int Number
        {
            get { return _num; }
        }

        public string Name
        {
            get { return _name; }
        }

        public string Description
        {
            get { return _desc; }
        }

        public POS PartOfSpeech
        {
            get { return _pos; }
        }
       
        public override String ToString()
        {
            return _name;
        }
        
        protected static String CheckString(String str)
        {
            str = str.Trim();
            if (str.Length == 0)
                throw new ArgumentException();
            return str;
        }

        private static Dictionary<int, LexFile> _casheLexFileMap = new Dictionary<int,LexFile>();
        private static void SetLexFileMap()
        {
            FieldInfo[] fields = typeof(LexFile).GetFields(BindingFlags.Static | BindingFlags.Public);
            LexFile lexFile;
            for (int i = 0; i < fields.Length; i++)
            {
                if (fields[i].FieldType == typeof(LexFile))
                {
                    lexFile = (LexFile)fields[i].GetValue(null);
                    _casheLexFileMap.Add(lexFile.Number, lexFile);
                }
            }
        }

        // all the lexical file descriptions declared in this class
        public static IEnumerable<LexFile> Values()
        {
            return _casheLexFileMap.Values;
        }

        // allows retrieval of one of the built-in lexical file descriptions given the number.
        public static LexFile GetLexicalFile(int num)
        {
            return _casheLexFileMap.ContainsKey(num) ? _casheLexFileMap[num] : null;
        }
    }
}
